臺股的三大法人是 外資、投信 以及 自營商,許多臺股投資人都會觀察三大法人買賣超作為投資決策的參考。為什麼要觀察三大法人進出呢?因為比起散戶,法人最大的優勢就在於資訊不對稱,機構法人握有豐富的全球數據和大量的研究人員分析總經情勢與產業變化。此外,除了公開法說會外,公司可能還有許多未公開的法人私訪行程,所以法人可以提早知道公司的內部狀況。所以我們經常發現,當公司利多消息見報時,往往股價已經先漲了一段,因為「凡事有人先知道」。
外資 研究的標的以 權值股、大型股 為主,因為外資的資金部位較大、投資週期也較長,當外資看好某檔股票時,不會一次就把部位建立起來,賣出持股也不會一次就把部位全數出清,所以通常會有連續性同方向的買賣行為。
Source:臺灣證券交易所
台積電(2330)就是非常典型由外資主導的超大型權值股。從上圖 2022 年初至 8 月 31 日的台積電股價與外資買賣超紀錄,我們可以發現台積電股價與外資買賣動向呈現高度連動,即便今年台積電已被外資大量提款,但根據 2022 年 8 月底證交所資料顯示,台積電的外資持股仍超過 70%。
在觀察外資籌碼要注意可能有「假外資」的問題。有些本土大戶會透過成立境外公司或透過外國券商帳戶買賣股票,這些買賣紀錄就會被歸類到外資,而真、假外資並無法在證交所和櫃買中心的盤後數據分辨出來。一般來說,權值股比較不會有假外資的問題,因為股本夠大不是少數幾個大戶就有辦法拉抬股價;如果是中小型公司,又不容易找到券商研究報告的個股,在交易所公布的盤後數據看到外資大買或大賣,就要小心可能是假外資所為。
投信 就是基金公司,因為不像外資有這麼龐大的資金部位,所以更偏好股本較小的 中、小型股,這類股票的股價波動比較大,也比較容易「作帳」。每逢季底、半年底和年底,投信基金會評比基金績效,投信為了績效考量,就會全力作帳,這就是我們在財經報導經常看到所謂「投信作帳股」或「投信作帳行情」。不過有作帳就會有「結帳」,特別是投信持股過高的股票,要小心可能有投信結帳的賣壓,尤其是股價已經漲了一段的中、小型飆股,漲得快,跌得也快。
Source:證券櫃檯買賣中心
我們以 台半(5425)為例,這是一檔上櫃股票,由於股本較小,所以股性也很活潑,上圖是 2022 年初至 8 月 31 日的台半股價與投信買賣超紀錄。當投信連續買超時,股價就容易漲上去;當投信連續費超時,股價就容易下跌。因為現在很多散戶也會根據法人進出做買賣,所以法人的連續買賣超,也有助長助跌的作用。
投信雖然比外資資金部位小,但具有在地優勢,對本土企業更熟悉,經常有未公開的法人私訪行程,容易更快掌握公司內部狀況。另外,根據法規規定,投信必須根據研究報告買賣股票,所以這些公司通常都具有一定基本面的支持,比較不容易選中地雷股,所以投信連續買超的股票是一般投資人可以參考的選股標的。
自營商 在證交所和櫃買中心公布的買賣數據分成「自行買賣」和「避險」。自行買買就是券商自營部使用自有資金進行的買賣行為;而避險主要是自營商用來對沖賣出權證的風險。什麼是權證?權證 是一種衍生性金融商品,它的本質很像股票選擇權,但是一般投資人只能做買方,發行權證的自營商則是賣方。當散戶買進權證,自營商為了避免可能承擔的損失,就會在現貨市場買進股票進行避險。
由於自營商的投資週期較短、操作更靈活,且每個操盤手都自己的操作習慣,還會使用期貨與選擇權等衍生性金融商品的交易策略,所以一般人比較難以理解背後的交易邏輯,這也是比較少人會去參考自營商籌碼做買賣的原因。
在證交所 三大法人買賣超日報 頁面,可以查詢上市股票三大法人買賣明細。
證交所首頁 > 交易資訊 > 三大法人 > 三大法人買賣超日報
在「三大法人買賣超日報」頁面選取「查詢日期」,因為我們是要查詢個股不需包含權證,在「分類項目」選擇「全部(不含權證、牛熊證、可展延牛熊證)」,然後按下「查詢」後,就會列出該日三大法人買賣明細。
點擊「列印 / HTML」連結,瀏覽器會開新分頁將資訊輸出成可列印的 HTML 頁面。假設資料日期為「民國 111 年 07 月 01 日」,我們會得到以下 URL:
https://www.twse.com.tw/fund/T86?response=html&date=20220701&selectType=ALLBUT0999
以上 URL 可設定的參數如下:
response
:回應資料的格式。指定 html
輸出 HTML 文件;改為 csv
可以另存 CSV 檔案;設定成 json
或不指定則回應 JSON 格式資料。date
:資料日期。接受的日期格式為 yyyyMMdd
,如 20220701
。type
:分類項目。 ALLBUT0999
表示分類項目是「全部(不含權證、牛熊證、可展延牛熊證)」。我們將 URL 查詢參數改為 response=json&date=20220701&type=ALLBUT0999
,證交所就會以 JSON 格式資料回應 2022 年 7 月 1 日的三大法人買賣明細:
{
"stat": "OK",
"date": "20220701",
"title": "111年07月01日 三大法人買賣超日報",
"fields": [
"證券代號",
"證券名稱",
"外陸資買進股數(不含外資自營商)",
"外陸資賣出股數(不含外資自營商)",
"外陸資買賣超股數(不含外資自營商)",
"外資自營商買進股數",
"外資自營商賣出股數",
"外資自營商買賣超股數",
"投信買進股數",
"投信賣出股數",
"投信買賣超股數",
"自營商買賣超股數",
"自營商買進股數(自行買賣)",
"自營商賣出股數(自行買賣)",
"自營商買賣超股數(自行買賣)",
"自營商買進股數(避險)",
"自營商賣出股數(避險)",
"自營商買賣超股數(避險)",
"三大法人買賣超股數"
],
"data": [
[
"00632R",
"元大台灣50反1 ",
"1,683,000",
"1,543,000",
"140,000",
"0",
"0",
"0",
"668,000",
"0",
"668,000",
"253,041,009",
"25,858,000",
"1,500,000",
"24,358,000",
"256,949,050",
"28,266,041",
"228,683,009",
"253,849,009"
],
......
],
"selectType": "ALLBUT0999",
"notes": [
"自營商表示證券自營商專戶。",
"投信表示本國投資信託基金。",
"外資及陸資表示依「華僑及外國人投資證券管理辦法」及「大陸地區投資人來臺從事證券投資及期貨交易管理辦法」辦理登記等投資人。",
"外資自營商買賣股數已計入自營商買賣股數,故不納入三大法人買賣股數之合計數計算。",
"本統計資訊含一般、零股、盤後定價、鉅額,不含拍賣、標購。",
"本資訊以當日原始成交情形統計,不以證券商申報錯帳、更正帳號等調整後資料統計。",
"ETF證券代號第六碼為K、M、S、C者,表示該ETF以外幣交易。"
]
}
到專案目錄開啟 src/scraper/twse-scraper.service.ts
檔案,在 TwseScraperService
實作 fetchEquitiesInstInvestorsTrades()
方法,取得上市股票三大法人買賣明細:
import * as _ from 'lodash';
import * as cheerio from 'cheerio';
import * as iconv from 'iconv-lite';
import * as numeral from 'numeral';
import { DateTime } from 'luxon';
import { firstValueFrom } from 'rxjs';
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { getTwseIndexSymbolByName } from '@speculator/common';
@Injectable()
export class TwseScraperService {
constructor(private httpService: HttpService) {}
async fetchEquitiesInstInvestorsTrades(date: string) {
// 將 `date` 轉換成 `yyyyMMdd` 格式
const formattedDate = DateTime.fromISO(date).toFormat('yyyyMMdd');
// 建立 URL 查詢參數
const query = new URLSearchParams({
response: 'json', // 指定回應格式為 JSON
date: formattedDate, // 指定資料日期
selectType: 'ALLBUT0999', // 指定分類項目為全部(不含權證、牛熊證、可展延牛熊證)
});
const url = `https://www.twse.com.tw/fund/T86?${query}`;
// 取得回應資料
const responseData = await firstValueFrom(this.httpService.get(url))
.then((response) => (response.data.stat === 'OK' ? response.data : null));
// 若該日期非交易日或尚無成交資訊則回傳 null
if (!responseData) return null;
// 整理回應資料
const data = responseData.data.reduce((tickers, row) => {
const [ symbol, name, ...values ] = row;
const [
foreignDealersExcludedBuy, // 外陸資買進股數(不含外資自營商)
foreignDealersExcludedSell, // 外陸資賣出股數(不含外資自營商)
foreignDealersExcludedNetBuySell, // 外陸資買賣超股數(不含外資自營商)
foreignDealersBuy, // 外資自營商買進股數
foreignDealersSell, // 外資自營商賣出股數
foreignDealersNetBuySell, // 外資自營商買賣超股數
sitcBuy, // 投信買進股數
sitcSell, // 投信賣出股數
sitcNetBuySell, // 投信買賣超股數
dealersNetBuySell, // 自營商買賣超股數
dealersProprietaryBuy, // 自營商買進股數(自行買賣)
dealersProprietarySell, // 自營商賣出股數(自行買賣)
dealersProprietaryNetBuySell, // 自營商買賣超股數(自行買賣)
dealersHedgeBuy, // 自營商買進股數(避險)
dealersHedgeSell, // 自營商賣出股數(避險)
dealersHedgeNetBuySell, // 自營商買賣超股數(避險)
instInvestorsNetBuySell, // 三大法人買賣超股數
] = values.map(value => numeral(value).value());
// 計算外資合計買進股數
const foreignInvestorsBuy = foreignDealersExcludedBuy + foreignDealersBuy;
// 外資合計賣出股數
const foreignInvestorsSell = foreignDealersExcludedSell + foreignDealersSell;
// 計算外資合計買賣超股數
const foreignInvestorsNetBuySell = foreignDealersExcludedNetBuySell + foreignDealersNetBuySell;
// 計算自營商合計買進股數
const dealersBuy = dealersProprietaryBuy + dealersHedgeBuy;
// 計算自營商合計賣出股數
const dealersSell = dealersProprietarySell + dealersHedgeSell;
const ticker = {
date,
symbol,
name: name.trim(),
foreignDealersExcludedBuy,
foreignDealersExcludedSell,
foreignDealersExcludedNetBuySell,
foreignDealersBuy,
foreignDealersSell,
foreignDealersNetBuySell,
foreignInvestorsBuy,
foreignInvestorsSell,
foreignInvestorsNetBuySell,
sitcBuy,
sitcSell,
sitcNetBuySell,
dealersProprietaryBuy,
dealersProprietarySell,
dealersProprietaryNetBuySell,
dealersHedgeBuy,
dealersHedgeSell,
dealersHedgeNetBuySell,
dealersBuy,
dealersSell,
dealersNetBuySell,
};
return [ ...tickers, ticker ];
}, []);
return data;
}
}
在 fetchEquitiesInstInvestorsTrades()
方法中,需要指定 date
參數,表示要取得上市股票三大法人買賣明細的日期。我們定義回傳的型別是一個陣列,每個陣列元素代表一檔股票的物件,物件欄位包含如下:
date
:日期symbol
:股票代號name
:股票名稱foreignDealersExcludedBuy
:外資及陸資(不含外資自營商)買進金額foreignDealersExcludedSell
:外資及陸資(不含外資自營商)賣出金額foreignDealersExcludedNetBuySell
:外資及陸資(不含外資自營商)買賣超foreignDealersBuy
:外資自營商買進金額foreignDealersSell
:外資自營商賣出金額foreignDealersNetBuySell
:外資自營商買賣超foreignInvestorsBuy
:外資合計買進金額foreignInvestorsSell
:外資合計賣出金額foreignInvestorsNetBuySell
:外資合計買賣超sitcBuy
:投信買進金額sitcSell
:投信賣出金額sitcNetBuySell
:投信買賣超dealersProprietaryBuy
:自營商(自行買賣)買進金額dealersProprietarySell
:自營商(自行買賣)賣出金額dealersProprietaryNetBuySell
:自營商(自行買賣)買賣超dealersHedgeBuy
:自營商(避險)買進金額dealersHedgeSell
:自營商(避險)賣出金額dealersHedgeNetBuySell
:自營商(避險)買賣超dealersBuy
:自營商合計買進金額dealersSell
:自營商合計賣出金額dealersNetBuySell
:自營商合計買賣超完成後,我們只要呼叫 TwseScraperService
的 fetchEquitiesInstInvestorsTrades()
方法,就可以按日期取得上市股票三大法人買賣明細。以日期 2022-07-01
為例:
[
{
date: '2022-07-01',
symbol: '00632R',
name: '元大台灣50反1',
foreignDealersExcludedBuy: 1683000,
foreignDealersExcludedSell: 1543000,
foreignDealersExcludedNetBuySell: 140000,
foreignDealersBuy: 0,
foreignDealersSell: 0,
foreignDealersNetBuySell: 0,
foreignInvestorsBuy: 1683000,
foreignInvestorsSell: 1543000,
foreignInvestorsNetBuySell: 140000,
sitcBuy: 668000,
sitcSell: 0,
sitcNetBuySell: 668000,
dealersProprietaryBuy: 25858000,
dealersProprietarySell: 1500000,
dealersProprietaryNetBuySell: 24358000,
dealersHedgeBuy: 256949050,
dealersHedgeSell: 28266041,
dealersHedgeNetBuySell: 228683009,
dealersBuy: 282807050,
dealersSell: 29766041,
dealersNetBuySell: 253041009
},
... 1125 more items
]
在櫃買中心網站的 三大法人買賣明細資訊 頁面,可以查詢上櫃股票三大法人買賣明細。
櫃買中心首頁 > 上櫃 > 三大法人 > 三大法人買賣明細資訊
在「三大法人買賣明細資訊」頁面「請選擇類股」選定「所有證券(不含權證、牛熊證)」,然後選取「資料日期」後,就會列出該日三大法人買賣明細。
點擊「列印/匯出HTML」連結,瀏覽器會開新分頁將資訊輸出成可列印的 HTML 頁面。假設資料日期為「111/07/01」,我們會得到以下 URL:
https://www.tpex.org.tw/web/stock/3insti/daily_trade/3itrade_hedge_result.php?l=zh-tw&o=htm&se=EW&t=D&d=111/07/01&s=0,asc
以上 URL 可設定的參數如下:
l
:輸出資料的語系。zh-tw
為正體中文;en-us
為英文。o
:資料輸出的格式。指定 htm
表示輸出 HTML 文件;改為 csv
可以另存 CSV 檔案;設定成 json
或不指定則回應 JSON 格式資料。se
:選擇的類股。EW
代表所有證券(不含權證、牛熊證)。t
:買賣明細的時間週期。D
為日報表;W
為週報表;M
為月報表。d
:資料日期。接受 民國年/月/日
的日期格式。需要注意,若 l
參數指定為 en-us
,則 d
參數需改成 西元年/月/日
的日期格式。s
:指定欄位要依照升冪或降冪排序。例如 0,asc
是按代號升冪排序;1,desc
則按名稱降冪排序,依此類推。我們將 URL 查詢參數改為 l=zh-tw&o=htm&se=EW&t=D&d=111/07/01
,櫃買中心就會以 JSON 格式資料回應 2022 年 7 月 1 日的上櫃股票三大法人買賣明細:
{
"reportTitle": "111年07月01日 三大法人日交易資訊(含普通股、鉅額、零股、綜合帳戶之投信買賣成交量)依股票代碼排序",
"reportDate": "111/07/01",
"iTotalRecords": 758,
"aaData": [
[
"00679B",
"元大美債20年",
"845,000",
"0",
"845,000",
"0",
"0",
"0",
"845,000",
"0",
"845,000",
"0",
"0",
"0",
"0",
"0",
"0",
"1,445,000",
"944,181",
"500,819",
"1,445,000",
"944,181",
"500,819",
"1,345,819",
"EE"
],
......
]
}
到專案目錄開啟 src/scraper/tpex-scraper.service.ts
檔案,在 TpexScraperService
實作 fetchEquitiesInstInvestorsTrades()
方法,取得上櫃股票三大法人買賣明細:
import * as _ from 'lodash';
import * as numeral from 'numeral';
import { DateTime } from 'luxon';
import { firstValueFrom } from 'rxjs';
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { Index, getTpexIndexSymbolByName, isWarrant } from '@speculator/common';
@Injectable()
export class TpexScraperService {
constructor(private httpService: HttpService) {}
...
async fetchEquitiesInstInvestorsTrades(date: string) {
// `date` 轉換成 `民國年/MM/dd` 格式
const dt = DateTime.fromISO(date);
const year = dt.get('year') - 1911;
const formattedDate = `${year}/${dt.toFormat('MM/dd')}`;
// 建立 URL 查詢參數
const query = new URLSearchParams({
l: 'zh-tw', // 指定語系為正體中文
o: 'json', // 指定回應格式為 JSON
se: 'EW', // 指定所有證券(不含權證、牛熊證)
t: 'D', // 指定日報表
d: formattedDate, // 指定資料日期
});
const url = `https://www.tpex.org.tw/web/stock/3insti/daily_trade/3itrade_hedge_result.php?${query}`;
// 取得回應資料
const responseData = await firstValueFrom(this.httpService.get(url))
.then((response) => response.data.iTotalRecords > 0 ? response.data : null);
// 若該日期非交易日或尚無成交資訊則回傳 null
if (!responseData) return null;
// 整理回應資料
const data = responseData.aaData.reduce((tickers, raw) => {
const [ symbol, name, ...values ] = raw;
const [
foreignDealersExcludedBuy, // 外資及陸資(不含外資自營商)買進股數
foreignDealersExcludedSell, // 外資及陸資(不含外資自營商)賣出股數
foreignDealersExcludedNetBuySell, // 外資及陸資(不含外資自營商)買賣超股數
foreignDealersBuy, // 外資自營商買進股數
foreignDealersSell, // 外資自營商賣出股數
foreignDealersNetBuySell, // 外資自營商買賣超股數
foreignInvestorsBuy, // 外資及陸資買進股數
foreignInvestorsSell, // 外資及陸資賣出股數
foreignInvestorsNetBuySell, // 外資及陸資買賣超股數
sitcBuy, // 投信買進股數
sitcSell, // 投信賣出股數
sitcNetBuySell, // 投信買賣超股數
dealersProprietaryBuy, // 自營商(自行買賣)買進股數
dealersProprietarySell, // 自營商(自行買賣)賣出股數
dealersProprietaryNetBuySell, // 自營商(自行買賣)買賣超股數
dealersHedgeBuy, // 自營商(避險)買進股數
dealersHedgeSell, // 自營商(避險)賣出股數
dealersHedgeNetBuySell, // 自營商(避險)買賣超股數
dealersBuy, // 自營商買進股數
dealersSell, // 自營商賣出股數
dealersNetBuySell, // 自營商買賣超股數
instInvestorsNetBuySell, // 三大法人買賣超股數合計
] = values.map(value => numeral(value).value());
const ticker = {
date,
symbol,
name,
foreignDealersExcludedBuy,
foreignDealersExcludedSell,
foreignDealersExcludedNetBuySell,
foreignDealersBuy,
foreignDealersSell,
foreignDealersNetBuySell,
foreignInvestorsBuy,
foreignInvestorsSell,
foreignInvestorsNetBuySell,
sitcBuy,
sitcSell,
sitcNetBuySell,
dealersProprietaryBuy,
dealersProprietarySell,
dealersProprietaryNetBuySell,
dealersHedgeBuy,
dealersHedgeSell,
dealersHedgeNetBuySell,
dealersBuy,
dealersSell,
dealersNetBuySell,
};
return [ ...tickers, ticker ];
}, []);
return data;
}
}
在 fetchEquitiesInstInvestorsTrades()
方法中,需要指定 date
參數,表示要取得上櫃股票三大法人買賣明細的日期。我們定義回傳的型別是一個陣列,每個陣列元素代表一檔股票的物件,物件欄位包含如下:
date
:日期symbol
:股票代號name
:股票名稱foreignDealersExcludedBuy
:外資及陸資(不含外資自營商)買進金額foreignDealersExcludedSell
:外資及陸資(不含外資自營商)賣出金額foreignDealersExcludedNetBuySell
:外資及陸資(不含外資自營商)買賣超foreignDealersBuy
:外資自營商買進金額foreignDealersSell
:外資自營商賣出金額foreignDealersNetBuySell
:外資自營商買賣超foreignInvestorsBuy
:外資合計買進金額foreignInvestorsSell
:外資合計賣出金額foreignInvestorsNetBuySell
:外資合計買賣超sitcBuy
:投信買進金額sitcSell
:投信賣出金額sitcNetBuySell
:投信買賣超dealersProprietaryBuy
:自營商(自行買賣)買進金額dealersProprietarySell
:自營商(自行買賣)賣出金額dealersProprietaryNetBuySell
:自營商(自行買賣)買賣超dealersHedgeBuy
:自營商(避險)買進金額dealersHedgeSell
:自營商(避險)賣出金額dealersHedgeNetBuySell
:自營商(避險)買賣超dealersBuy
:自營商合計買進金額dealersSell
:自營商合計賣出金額dealersNetBuySell
:自營商合計買賣超完成後,我們只要呼叫 TpexScraperService
的 fetchEquitiesInstInvestorsTrades()
方法,就可以按日期取得上櫃股票三大法人買賣明細。以日期 2022-07-01
為例:
[
{
date: '2022-07-01',
symbol: '00679B',
name: '元大美債20年',
foreignDealersExcludedBuy: 845000,
foreignDealersExcludedSell: 0,
foreignDealersExcludedNetBuySell: 845000,
foreignDealersBuy: 0,
foreignDealersSell: 0,
foreignDealersNetBuySell: 0,
foreignInvestorsBuy: 845000,
foreignInvestorsSell: 0,
foreignInvestorsNetBuySell: 845000,
sitcBuy: 0,
sitcSell: 0,
sitcNetBuySell: 0,
dealersProprietaryBuy: 0,
dealersProprietarySell: 0,
dealersProprietaryNetBuySell: 0,
dealersHedgeBuy: 1445000,
dealersHedgeSell: 944181,
dealersHedgeNetBuySell: 500819,
dealersBuy: 1445000,
dealersSell: 944181,
dealersNetBuySell: 500819
},
... 757 more items
]
本系列文已正式出版為《Node.js 量化投資全攻略:從資料收集到自動化交易系統建構實戰》。本書新增了全新內容和實用範例,為你提供更深入的學習體驗!歡迎參考選購,開始你的量化投資之旅!
天瓏網路書店連結:https://www.tenlong.com.tw/products/9786263336070